/*
 * GangstersGrid.java
 *
 * Created on Sobota, 2007, november 3, 0:59
 */

package gui;

import gui.editor.EditorPanel;
import gui.editor.TopologyEditorListener;
import java.awt.Color;
import java.awt.ContainerOrderFocusTraversalPolicy;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FocusTraversalPolicy;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.regex.Pattern;
import javax.swing.ButtonGroup;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.ScrollPaneConstants;
import javax.swing.filechooser.FileNameExtensionFilter;
import logic.JSimulation;
import logic.SimulationParameters;
import logic.gridNodes.GridBroker;
import logic.gridNodes.GridBrokerGlobal;
import logic.gridNodes.GridResource;
import logic.gridNodes.GridRouterGlobal;
import logic.gridNodes.GridRouterLocal;
import logic.gridNodes.GridUser;
import logic.gridSimInterface.SimTags;
import logic.schedulers.AbstractSchedulerOptimization;
import logic.schedulers.AlgorithmCollection;
import logic.schedulers.AlgorithmPlugin;
import logic.schedulers.ParametersDialog;
import logic.topology.GridTopology;
import logic.topology.NetworkLink;
import logic.topology.NetworkNode;
import logicTests.Dbg;
import xml.XmlTopology;

/**
 *
 * @author  alvin
 */
public class GangstersGrid extends javax.swing.JFrame {
    
    private EditorPanel editor;
    private SimulationDialogMultiple simulationDlg = new SimulationDialogMultiple(this);
//    private SimulationDialog simulationDlg = new SimulationDialog(this);
    
    private int rightPanelMinSize = 350;
    
    
    ParametersPanel panelNetLink = new NetworkLinkJPanel();
    ParametersPanel panelBrokerLocal = new GridBrokerLocalJPanel();
    ParametersPanel panelBrokerGlobal = new GridBrokerGlobalJPanel();
    ParametersPanel panelRouterGlobal = new GridRouterGlobalJPanel();
    ParametersPanel panelRouterLocal = new GridRouterLocalJPanel();
    ParametersPanel panelResource = new GridResourceJPanel();
    ParametersPanel panelUser = new GridUserJPanel(this);
    JPanel panelNull = new JPanel();
    JPanel actualRightPanel;
    
    
    JScrollPane rightPane;
    JMenuItem LocalSchedulingParameters = null;
    JMenuItem GlobalSchedulingParameters = null;
    private JFileChooser fileChooser = new JFileChooser();
    private FileNameExtensionFilter filter = new FileNameExtensionFilter("XML file", "xml");
    
    
    /** Creates new form GangstersGrid */
    public GangstersGrid() {
        initComponents();
        setLocationRelativeTo(null);
        setExtendedState(JFrame.MAXIMIZED_BOTH);
        
        fileChooser.setFileFilter(filter);
        
        ButtonGroup costFunctionBG = new ButtonGroup();
        costFunctionBG.add(CostFinTimeJRadBtn);
        costFunctionBG.add(CostLatJRadBtn);
        
        ButtonGroup planningTypeBG = new ButtonGroup();
        planningTypeBG.add(DynPlanJRadBtn);
        planningTypeBG.add(StatPlanJRadBtn);
        
        CostFinTimeJRadBtn.doClick();
        DynPlanJRadBtn.doClick();
        
        ////////////////////////////////////////////////////////////////////////
        //DYNAMICKE NAPLNENIE MENU - LOCAL, GLOBAL
        int activeLocalAlg = 0;
        int activeGlobalAlg = 0;
        AlgorithmCollection.loadAlgorithms();
        AlgorithmCollection.createDialogs(this);
        
        ButtonGroup optimizationBG = new ButtonGroup();
        JMenuItem jmi = null;
        JMenuItem activeAlgMenuItem = null;
        for (int i = 0; i < AlgorithmCollection.getLocalSchedulingCount(); i++) {
            AlgorithmPlugin ap = AlgorithmCollection.getLocalScheduling(i);
            jmi = new JRadioButtonMenuItem(ap.getName(), i == activeLocalAlg);
            LocalJMenu.add(jmi);
            optimizationBG.add(jmi);
            jmi.addActionListener(new LocalSchedulingMenuListener(i));
            if ( i == activeLocalAlg )
                activeAlgMenuItem = jmi;
        }
        LocalJMenu.add(new JSeparator());
        LocalSchedulingParameters = new JMenuItem("Parameters");
        LocalSchedulingParameters.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showParamDialog(SimulationParameters.getLocalScheduler());
            }
        });
        LocalJMenu.add(LocalSchedulingParameters);
        activeAlgMenuItem.doClick();
        
        ButtonGroup schedulingBG = new ButtonGroup();
        activeAlgMenuItem = null;
        for (int i = 0; i < AlgorithmCollection.getGlobalSchedulingCount(); i++) {
            AlgorithmPlugin ap = AlgorithmCollection.getGlobalScheduling(i);
            jmi = new JRadioButtonMenuItem(ap.getName(), i == activeGlobalAlg);
            GlobalJMenu.add(jmi);
            schedulingBG.add(jmi);
            jmi.addActionListener(new GlobalSchedulingMenuListener(i));
            if ( i == activeGlobalAlg )
                activeAlgMenuItem = jmi;
        }
        GlobalJMenu.add(new JSeparator());
        GlobalSchedulingParameters = new JMenuItem("Parameters");
        GlobalSchedulingParameters.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showParamDialog(SimulationParameters.getGlobalScheduler());
            }
        });
        GlobalJMenu.add(GlobalSchedulingParameters);
        activeAlgMenuItem.doClick();
        
        ////////////////////////////////////////////////////////////////////////
        //VYTVORENIE EDITOR PANELA
        panelNull.setPreferredSize(new Dimension(rightPanelMinSize-40, 10));
        
        editor = new EditorPanel();
        editor.setBackground(Color.white);
        editor.setLayout(null);
        
        int vert = ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
        int horiz = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
        
        JScrollPane scrollPane = new JScrollPane(editor,vert,horiz);
        scrollPane.setPreferredSize(new Dimension(200,200));
        
        rightPane = new JScrollPane(panelNull,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        actualRightPanel = panelNull;
        
        mainPanel.setLeftComponent(scrollPane);
        mainPanel.setRightComponent(rightPane);
        mainPanel.setDividerLocation(mainPanel.getWidth() - rightPanelMinSize);
        
        editor.scrollRectToVisible(new Rectangle(2000,2000,1,1));
        editor.addEditorListener(new MyEditorListener());
    }
    
    private void showParamDialog(AlgorithmPlugin ap) {
        ParametersDialog pd = ap.getParamDialog();
        pd.setParameters(ap.getParameters());
        pd.setLocationRelativeTo(this);
        pd.setVisible(true);
    }
    
    private class LocalSchedulingMenuListener implements ActionListener {
        private int index;
        public LocalSchedulingMenuListener(int algorithmIndex) {
            index = algorithmIndex;
        }
        public void actionPerformed(ActionEvent e) {
            SimulationParameters.setLocalScheduler(
                    AlgorithmCollection.getLocalScheduling(index));
            LocalSchedulingParameters.setEnabled(
                    SimulationParameters.getLocalScheduler().getParamDialog() != null
                    );
        }
    }
    
    private class GlobalSchedulingMenuListener implements ActionListener {
        private int index;
        public GlobalSchedulingMenuListener(int algorithmIndex) {
            index = algorithmIndex;
        }
        public void actionPerformed(ActionEvent e) {
            SimulationParameters.setGlobalScheduler(
                    AlgorithmCollection.getGlobalScheduling(index));
            GlobalSchedulingParameters.setEnabled(
                    SimulationParameters.getGlobalScheduler().getParamDialog() != null
                    );
        }
    }
    private class MyEditorListener implements TopologyEditorListener {
        /**
         * Vytvara panel pre nastavenie potrebnych parametrov podla typu uzla
         * @param o je uzol pre ktory sa vytvori potrebny panel
         */
        public void ObjectSelected(Object o) {
//            JPanel panelRight = (JPanel) mainPanel.getRightComponent();
            JPanel panelRight = actualRightPanel;
            JPanel panel = null;
            if (panelRight instanceof ParametersPanel) {
                ((ParametersPanel)panelRight).saveObjectValues();
            }
            
            if (o == null){
                panel = panelNull;
            }else {
                if (o instanceof NetworkLink) { // ak sa jedna o linku
                    panel = panelNetLink;
                } else { // ak sa jedna o uzol
                    if (o instanceof GridBroker) { // ak sa jedna o localneho brokera
                        panel = panelBrokerLocal;
                    } else if (o instanceof GridBrokerGlobal) { // ak sa jedna o globalneho brokera
                        panel = panelBrokerGlobal;
                    } else if (o instanceof GridRouterGlobal) { // ak sa jedna o globalneho routera
                        panel = panelRouterGlobal;
                    } else if (o instanceof GridRouterLocal) { // ak sa jedna o localneho routera
                        panel = panelRouterLocal;
                    } else if (o instanceof GridResource) { // ak sa jedna o resource
                        panel = panelResource;
                    } else if (o instanceof GridUser) { // ak sa jedna usera
                        panel = panelUser;
                    }
                }
                ((ParametersPanel)panel).setObject(o);
            }
            mainPanel.setDividerLocation(mainPanel.getWidth() - rightPanelMinSize);
            rightPane = new JScrollPane(panel,
                    ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                    ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            actualRightPanel = panel;
            mainPanel.setRightComponent(rightPane);
        }
        
        public void ExceptionCaught(Exception e) {
            showErrorMessage(e.getMessage());
        }
        
    }
    public static void showErrorMessage(String text) {
        JOptionPane.showMessageDialog(null,text,"ERROR",JOptionPane.ERROR_MESSAGE);
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        mainPanel = new javax.swing.JSplitPane();
        jMenuBar1 = new javax.swing.JMenuBar();
        FileJMenu = new javax.swing.JMenu();
        NewPJMenuItm = new javax.swing.JMenuItem();
        OpenPJMenuItm = new javax.swing.JMenuItem();
        SavePJMenuItm = new javax.swing.JMenuItem();
        ExitJMenuItm = new javax.swing.JMenuItem();
        SimulationJMenu = new javax.swing.JMenu();
        CostLatJRadBtn = new javax.swing.JRadioButtonMenuItem();
        CostFinTimeJRadBtn = new javax.swing.JRadioButtonMenuItem();
        PrvySepJSep = new javax.swing.JSeparator();
        DynPlanJRadBtn = new javax.swing.JRadioButtonMenuItem();
        StatPlanJRadBtn = new javax.swing.JRadioButtonMenuItem();
        jSeparator1 = new javax.swing.JSeparator();
        StartJMenuItm = new javax.swing.JMenuItem();
        LocalJMenu = new javax.swing.JMenu();
        GlobalJMenu = new javax.swing.JMenu();
        HelpJMenu = new javax.swing.JMenu();
        UserManulJMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("GangstersGrid");
        mainPanel.setDividerLocation(300);
        mainPanel.setEnabled(false);
        mainPanel.setFocusTraversalPolicy(getFocusTraversalPolicy());
        mainPanel.addHierarchyBoundsListener(new java.awt.event.HierarchyBoundsListener() {
            public void ancestorMoved(java.awt.event.HierarchyEvent evt) {
            }
            public void ancestorResized(java.awt.event.HierarchyEvent evt) {
                mainPanelAncestorResized(evt);
            }
        });

        FileJMenu.setText("File");
        NewPJMenuItm.setText("New project");
        NewPJMenuItm.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                NewPJMenuItmActionPerformed(evt);
            }
        });

        FileJMenu.add(NewPJMenuItm);

        OpenPJMenuItm.setText("Open project");
        OpenPJMenuItm.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                OpenPJMenuItmActionPerformed(evt);
            }
        });

        FileJMenu.add(OpenPJMenuItm);

        SavePJMenuItm.setText("Save project");
        SavePJMenuItm.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                SavePJMenuItmActionPerformed(evt);
            }
        });

        FileJMenu.add(SavePJMenuItm);

        ExitJMenuItm.setText("Exit");
        ExitJMenuItm.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ExitJMenuItmActionPerformed(evt);
            }
        });

        FileJMenu.add(ExitJMenuItm);

        jMenuBar1.add(FileJMenu);

        SimulationJMenu.setText("Simulation");
        CostLatJRadBtn.setText("Cost by latency");
        CostLatJRadBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                CostLatJRadBtnActionPerformed(evt);
            }
        });

        SimulationJMenu.add(CostLatJRadBtn);

        CostFinTimeJRadBtn.setText("Cost by finish-time");
        CostFinTimeJRadBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                CostFinTimeJRadBtnActionPerformed(evt);
            }
        });

        SimulationJMenu.add(CostFinTimeJRadBtn);

        SimulationJMenu.add(PrvySepJSep);

        DynPlanJRadBtn.setText("Dynamic planning");
        DynPlanJRadBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                DynPlanJRadBtnActionPerformed(evt);
            }
        });

        SimulationJMenu.add(DynPlanJRadBtn);

        StatPlanJRadBtn.setText("Static planning");
        StatPlanJRadBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                StatPlanJRadBtnActionPerformed(evt);
            }
        });

        SimulationJMenu.add(StatPlanJRadBtn);

        SimulationJMenu.add(jSeparator1);

        StartJMenuItm.setText("Start");
        StartJMenuItm.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                StartJMenuItmActionPerformed(evt);
            }
        });

        SimulationJMenu.add(StartJMenuItm);

        jMenuBar1.add(SimulationJMenu);

        LocalJMenu.setText("Local");
        jMenuBar1.add(LocalJMenu);

        GlobalJMenu.setText("Global");
        jMenuBar1.add(GlobalJMenu);

        HelpJMenu.setText("Help");
        UserManulJMenuItem.setText("User manual");
        UserManulJMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                UserManulJMenuItemActionPerformed(evt);
            }
        });

        HelpJMenu.add(UserManulJMenuItem);

        jMenuBar1.add(HelpJMenu);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mainPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 543, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mainPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 389, Short.MAX_VALUE)
        );
        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void UserManulJMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_UserManulJMenuItemActionPerformed
        Desktop desktop = Desktop.getDesktop();
        try {
            File f = new File("Uzivatelska_prirucka.htm");
            desktop.browse(f.getAbsoluteFile().toURI());
        } catch (Exception ex) {
            ex.printStackTrace();
        }        
    }//GEN-LAST:event_UserManulJMenuItemActionPerformed
    
    private void ExitJMenuItmActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ExitJMenuItmActionPerformed
        System.exit(0);
    }//GEN-LAST:event_ExitJMenuItmActionPerformed
    
    private void NewPJMenuItmActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_NewPJMenuItmActionPerformed
        GridTopology.clear();
        editor.vymazTopologiu();
    }//GEN-LAST:event_NewPJMenuItmActionPerformed
    
    private void SavePJMenuItmActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_SavePJMenuItmActionPerformed
        try {
            int return_val = fileChooser.showSaveDialog(this);
            if(return_val == fileChooser.APPROVE_OPTION) {
                String subor = fileChooser.getSelectedFile().getAbsolutePath();
                if(subor.length() > 4) {
                    if (!subor.substring(subor.length() - 4).equals(".xml")) {
                        subor = subor.concat(".xml") ;
                    }
                    
                }
                XmlTopology.saveTopology(subor);
//                XmlTopology.saveTopology(fileChooser.getSelectedFile().getAbsoluteFile().toURI().toURL().toString());
//                System.out.println(fileChooser.getSelectedFile().getAbsoluteFile().toURI().toURL().toString());
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }//GEN-LAST:event_SavePJMenuItmActionPerformed
    
    private void OpenPJMenuItmActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_OpenPJMenuItmActionPerformed
        GridTopology.clear();
        try {
            int return_val = fileChooser.showOpenDialog(this);
            if(return_val == fileChooser.APPROVE_OPTION) {
                editor.vymazTopologiu();
                XmlTopology.loadTopology(fileChooser.getSelectedFile().getAbsoluteFile().toURI().toURL().toString(), editor);
                editor.vytvorTopologiu();
            }
            
        } catch (Exception ex) {
            ex.printStackTrace();
            editor.vymazTopologiu();
        }
        
        //TODO: pri chybe nacitania vymazat celu novu topologiu
    }//GEN-LAST:event_OpenPJMenuItmActionPerformed
    
    private void CostFinTimeJRadBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CostFinTimeJRadBtnActionPerformed
        SimulationParameters.setCostFunction(SimTags.COST_BY_FINISH_TIME);
    }//GEN-LAST:event_CostFinTimeJRadBtnActionPerformed
    
    private void CostLatJRadBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CostLatJRadBtnActionPerformed
        SimulationParameters.setCostFunction(SimTags.COST_BY_LATENCY);
    }//GEN-LAST:event_CostLatJRadBtnActionPerformed
    
    private void DynPlanJRadBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_DynPlanJRadBtnActionPerformed
        SimulationParameters.setPlanningType(SimTags.DYNAMIC_PLANNING);
        Dbg.vypis("DynPlanJRadBTNActionPerformed");
    }//GEN-LAST:event_DynPlanJRadBtnActionPerformed
    
    private void StatPlanJRadBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_StatPlanJRadBtnActionPerformed
        SimulationParameters.setPlanningType(SimTags.STATIC_PLANNING);
        Dbg.vypis("StatPlanJRadBtnActionPerformed");
    }//GEN-LAST:event_StatPlanJRadBtnActionPerformed
    
    private void mainPanelAncestorResized(java.awt.event.HierarchyEvent evt) {//GEN-FIRST:event_mainPanelAncestorResized
        mainPanel.setDividerLocation(mainPanel.getWidth() - rightPanelMinSize);
    }//GEN-LAST:event_mainPanelAncestorResized
    
    private void StartJMenuItmActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_StartJMenuItmActionPerformed
        editor.selectNull();
        
        panelNull.setLayout(new FlowLayout());
        panelNull.removeAll();
        LinkedList<String> topologyErrors = JSimulation.checkTopology();
        if (topologyErrors != null) {
            for (String error : topologyErrors)
                panelNull.add(new JLabel(error));
            return;
        }
        simulationDlg.setLocationRelativeTo(this);
        simulationDlg.start();
        simulationDlg.setVisible(true);
        
    }//GEN-LAST:event_StartJMenuItmActionPerformed
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new GangstersGrid().setVisible(true);
            }
        });
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JRadioButtonMenuItem CostFinTimeJRadBtn;
    private javax.swing.JRadioButtonMenuItem CostLatJRadBtn;
    private javax.swing.JRadioButtonMenuItem DynPlanJRadBtn;
    private javax.swing.JMenuItem ExitJMenuItm;
    private javax.swing.JMenu FileJMenu;
    private javax.swing.JMenu GlobalJMenu;
    private javax.swing.JMenu HelpJMenu;
    private javax.swing.JMenu LocalJMenu;
    private javax.swing.JMenuItem NewPJMenuItm;
    private javax.swing.JMenuItem OpenPJMenuItm;
    private javax.swing.JSeparator PrvySepJSep;
    private javax.swing.JMenuItem SavePJMenuItm;
    private javax.swing.JMenu SimulationJMenu;
    private javax.swing.JMenuItem StartJMenuItm;
    private javax.swing.JRadioButtonMenuItem StatPlanJRadBtn;
    private javax.swing.JMenuItem UserManulJMenuItem;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSplitPane mainPanel;
    // End of variables declaration//GEN-END:variables
    
}
